#include <iomanip>
#include "Complex.h"

Complex::Complex(double Re, double Im) 
    : Re(Re), Im(Im) {}
Complex::Complex(double d)
    : Re(d) {}

Complex Complex::operator~(void) const
{
    return Complex(this->Re, -this->Im);
}

Complex Complex::operator-(void)const
{
    return Complex(-this->Re, -this->Im);
}

ostream& operator<<(ostream& os, const Complex& c)
{
    std::cout << std::fixed << std::setprecision(2);
    if (fabs(c.Re) < pow(10, -5) && fabs(c.Im) < pow(10, -5)) {
        std::cout << "0.00";
    }
    else if (fabs(c.Re) < pow(10, -5)) {
        std::cout << c.Im << "i";
    }
    else if (fabs(c.Im) < pow(10, -5)) {
        std::cout << c.Re;
    }
    else {
        if (c.Im > 0) {
            std::cout << c.Re << " + " << c.Im << "i";
        }
        else {
            std::cout << c.Re << " - " << fabs(c.Im) << "i";
        } 
    }

    return os;
}

Complex operator+(Complex c1, Complex c2)
{
    return Complex(c1.Re + c2.Re, c1.Im + c2.Im);
}

Complex operator-(Complex c1, Complex c2)
{
    return Complex(c1.Re - c2.Re, c1.Im - c2.Im);
}

Complex operator*(Complex c1, Complex c2)
{
    double a = c1.Re, b = c1.Im, c = c2.Re, d = c2.Im;
    return Complex(a * c - b * d, a * d + b * c);
}

Complex operator/(Complex c1, Complex c2)
{
    double a = c1.Re, b = c1.Im, c = c2.Re, d = c2.Im;
    return Complex((a * c + b * d) / (c * c + d * d), (b * c - a * d) / (c * c + d * d));   
}

double abs(Complex& c)
{
    return sqrt(pow(c.Re, 2) + pow(c.Im, 2));
}

Complex operator""i(unsigned long long Im)
{
    return Complex(0, Im);
}

Complex operator""i(long double Im)
{
    return Complex(0, Im);
} 